package com.example.demo.config;

import com.example.demo.queue.factory.LogEventFactory;
import com.example.demo.queue.factory.TestEventFactory;
import com.example.demo.queue.handler.LogEventHandler;
import com.example.demo.queue.handler.TestEventHandler;
import com.example.demo.queue.message.LogEvent;
import com.example.demo.queue.message.TestEvent;
import com.example.demo.queue.producer.LogEventProducer;
import com.example.demo.queue.producer.TestEventProducer;
import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;

import java.util.concurrent.Executors;

@Configuration
@RequiredArgsConstructor
public class DisruptorConfig {
    private final MongoTemplate mongoTemplate;

    @Bean
    public Disruptor<LogEvent> disruptor1() {
        int bufferSize = 1024;
        Disruptor<LogEvent> disruptor = new Disruptor<>(new LogEventFactory(), bufferSize, Executors.defaultThreadFactory());

        // 绑定事件处理器
        disruptor.handleEventsWith(new LogEventHandler(mongoTemplate));
        disruptor.start();
        return disruptor;
    }

    @Bean
    public LogEventProducer logEventProducer(Disruptor<LogEvent> disruptor) {
        return new LogEventProducer(disruptor.getRingBuffer());
    }


    @Bean
    public Disruptor<TestEvent> disruptor2() {
        int bufferSize = 1024;
        /*
         * 1、Disruptor队列不受设置的线程数影响，队列里的消息执行完一个再到下一个，全都使用同一个线程执行
         * 2、似乎只能用默认线程池，或者在此处重新创建线程池
         **/
        Disruptor<TestEvent> disruptor = new Disruptor<>(new TestEventFactory(), bufferSize, Executors.defaultThreadFactory(), ProducerType.SINGLE, new BlockingWaitStrategy());

        // 绑定事件处理器
        disruptor.handleEventsWith(new TestEventHandler());
        disruptor.start();
        return disruptor;
    }

    @Bean
    public TestEventProducer testEventProducer(Disruptor<TestEvent> disruptor) {
        return new TestEventProducer(disruptor.getRingBuffer());
    }
}
